package cn.zxf.note.note.review;

import cn.zxf.note.common.jpa.AbstractDao;
import cn.zxf.note.note.review.dto.NoteReviewItemDto;
import cn.zxf.note.note.review.dto.NoteReviewListDto;
import com.github.zengxf.common.domain.Pair;
import com.github.zengxf.common.utils.DateUtils;
import com.github.zengxf.common.utils.ListUtils;
import com.github.zengxf.sqlbuilder.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class NoteReviewDao extends AbstractDao {

    public List<NoteReviewItemDto> findList(Integer userId, LocalDate date, Integer status) {
        Pair<LocalDateTime> dates = DateUtils.toTimes(date);
        SqlResult res = SelectBuilder.of()
                .table("note_review nr")
                .addField("nr.id", "review_id")
                .addField("nr.frequency", "review_frequency")
                .addField("note_id")
                .addField("n.title", "note_title")
                .addField("nt.id", "type_id")
                .addField("nt.`name`", "type_name")
                .addJoin(DbJoin.left("note n", DbCriteria.ofLiteral("nr.note_id", DbCriteriaType.EQ, "n.id")))
                .addJoin(DbJoin.left("note_type nt", DbCriteria.ofLiteral("n.type_id", DbCriteriaType.EQ, "nt.id")))
                .where(
                        DbCriteria.eq("nr.user_id", userId),
                        DbCriteria.eq("nr.status", status),
                        DbCriteria.between("review_date", dates.v1, dates.v2)
                )
                .setSort(DbSort.of().desc("type_id").asc("note_id"))
                .build();
        RowMapper<NoteReviewItemDto> rm = BeanPropertyRowMapper.newInstance(NoteReviewItemDto.class);
        return super.namedJdbc.query(res.sql, res.param, rm);
    }

    public String findNotReviewRecentDate(Integer userId) {
        SqlResult sql = SelectBuilder.of()
                .table("note_review")
                .addField("DATE_FORMAT(review_date, '%Y-%m-%d')", "dt")
                .where(DbCriteriaGroup.ofAnd()
                        .addItem(DbCriteria.of("user_id", DbCriteriaType.EQ, userId))
                        .addItem(DbCriteria.of("status", DbCriteriaType.EQ, NoteReviewStatusEnum.INITIAL.code))
                        .addItem(DbCriteria.of("review_date", DbCriteriaType.BETWEEN,
                                (Object[]) DateUtils.lastMonth().toArray())
                        )
                )
                .setSort(DbSort.of().asc("dt"))
                .page(0, 1)
                .build();
        List<String> list = super.namedJdbc.queryForList(sql.getSql(), sql.getParam(), String.class);
        return ListUtils.one(list);
    }

    public int updateStatus(Integer id, Integer status, Date date) {
        SqlResult res = UpdateBuilder.of()
                .table("note_review")
                .addSet(DbSet.of("status", status))
                .addSet(DbSet.of("reviewed_date", date))
                .where(DbCriteriaGroup.ofAnd(
                        DbCriteria.eq("id", id)
                ))
                .build();
        return super.namedJdbc.update(res.sql, res.param);
    }

    /*** 修改同一笔记的复习时间，往后或往前移动天数 */
    public int updateDateAddDays(Integer noteId, Integer refId, int days) {
        String sql = "UPDATE note_review " +
                " SET review_date = DATE_ADD(review_date, INTERVAL %d DAY) " +
                " WHERE note_id = %s AND id > %d AND status = 1";
        sql = String.format(sql, days, noteId, refId);
        log.debug("updateDateAddDays sql: \n\n{}\n", sql);
        return super.jdbc.update(sql);
    }

    public List<NoteReviewListDto> findList(Integer userId, Integer noteId) {
        SqlResult res = SelectBuilder.of()
                .table("note_review")
                .addFields("id", "status", "review_date", "reviewed_date", "frequency")
                .where(
                        DbCriteria.eq("user_id", userId),
                        DbCriteria.eq("note_id", noteId),
                        DbCriteria.in("status",
                                List.of(NoteReviewStatusEnum.INITIAL.code, NoteReviewStatusEnum.REVIEWED.code)
                        )
                )
                .setSort(DbSort.of().asc("review_date"))
                .build();
        RowMapper<NoteReviewListDto> rm = BeanPropertyRowMapper.newInstance(NoteReviewListDto.class);
        return super.namedJdbc.query(res.sql, res.param, rm);
    }

    // 逻辑删除，要不然前端会有问题
    public void deleteNotReviewed(Integer userId, Integer noteId) {
        SqlResult res = UpdateBuilder.of()
                .table("note_review")
                .addSet(DbSet.of("status", NoteReviewStatusEnum.CLEARED.code))
                .where(DbCriteriaGroup.ofAnd(
                        DbCriteria.eq("user_id", userId),
                        DbCriteria.eq("note_id", noteId),
                        DbCriteria.eq("status", NoteReviewStatusEnum.INITIAL.code)
                ))
                .build();
        super.namedJdbc.update(res.sql, res.param);
    }

}
